
package threads.collaboration;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class StringProcessorRunner
{

	private static int counter = 1;

	public static void main(String[] args)
	{

		String source = StringProvider.getBigString(100000000);
		System.out.println("size of source string is " + source.length());
		List<String> parts = new ArrayList<String>();

		int partSize = source.length() / counter;
		int balanceSize = source.length() % counter;

		for (int i = 0; i < counter; i++)
		{
			if (balanceSize != 0 && counter - i == 1)
			{
				parts.add(source.substring(i * partSize, source.length()));
			}
			else
			{
				parts.add(source.substring(i * partSize, (i + 1) * partSize));
			}
		}

//		System.out.println(parts);
//
//		System.out.println("partSize=" + partSize);
//		System.out.println("balanceSize=" + balanceSize);

		List<Callable<ResultWrapper>> workers = new ArrayList<Callable<ResultWrapper>>();
		CountDownLatch latch = new CountDownLatch(counter);
		for (String part : parts)
		{
			StringProcessingThread worker = new StringProcessingThread(latch, part,
					parts.indexOf(part));
			workers.add(worker);
		}

		ExecutorService exec = Executors.newCachedThreadPool();
		Future<String> resultingFuture = exec.submit(new ResultingFutureThread(latch, source));

		List<Future<ResultWrapper>> results = new ArrayList<Future<ResultWrapper>>();
		long generalStart = System.currentTimeMillis();
		
		try
		{
			results = exec.invokeAll(workers);
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}

		while (!resultingFuture.isDone())
		{

		}
		long generalEnd = System.currentTimeMillis();
		exec.shutdown();
		
		StringBuilder sb = new StringBuilder();
		
		List<ResultWrapper> resultWrappers = new ArrayList<ResultWrapper>();
		
		for (Future<ResultWrapper> future : results)
		{
			
			ResultWrapper wrapper;
			try
			{
				wrapper = future.get();
				resultWrappers.add(wrapper);
			}
			catch (InterruptedException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			catch (ExecutionException e)
			{
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		Collections.sort(resultWrappers);
		
		for (ResultWrapper resultWrapper : resultWrappers)
		{
			sb.append(resultWrapper.getResultString());
		}
		
		System.out.println("all finished");
		System.out.println("general time " + (generalEnd - generalStart) + " ms");
		
		String test = new StringBuilder(sb).reverse().toString();
		System.out.println(test.equals(source));
	}

}
